/*
 * HibernateSearchVisitor.java Copyright 2004 Paul Mukherjee
 */
package org.nanhill.support.hibernate.search.demo.filesearch;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Expression;
import org.nanhill.commons.pattern.search.SearchCriterion;
import org.nanhill.commons.pattern.search.SearchException;
import org.nanhill.support.hibernate.search.CriteriaSearchVisitor;

/**
 * @author pmu
 * @version $Revision: 1.7 $
 * 
 * Implementation of ISearchVisitor specific to Hibernate.
 */
public class VolumeHibernateSearchVisitor extends CriteriaSearchVisitor
		implements VolumeSearchVisitor {
	private Criteria criteria;

	/**
	 * Creates an instance of this class, using the session to initialize the
	 * Criteria.
	 * 
	 * @param session
	 *            The session used to initialize the Criteria
	 */
	public VolumeHibernateSearchVisitor(Session session, Class entityClz) {
		criteria = session.createCriteria(entityClz);
	}

	/**
	 * Visits a SearchVolumeName search criterion.
	 * 
	 * @param volumeName
	 *            The SearchVolumeName to be visited.
	 * @throws SearchException
	 *             Propogates Hibernate exceptions.
	 * @see uk.me.mukherjee.archivedb.pd.search.SearchVisitor#visitVolumeName(uk.me.mukherjee.archivedb.pd.search.criteria.SearchVolumeName)
	 */
	public void visitVolumeName(SearchVolumeName volumeName)
			throws SearchException {
		try {
			Criteria volumeCriteria = criteria.createCriteria("volume");
			volumeCriteria.add(Expression.like("name", addWildcards(volumeName
					.getValue())));
		} catch (HibernateException e) {
			throw new SearchException(e);
		}
	}

	/**
	 * Visits a SearchFilename search criterion.
	 * 
	 * @param filename
	 *            The SearchFilename to be visited.
	 * @see uk.me.mukherjee.archivedb.pd.search.SearchVisitor#visitFilename(uk.me.mukherjee.archivedb.pd.search.criteria.SearchFilename)
	 */
	public void visitFilename(SearchFilename filename) {
		criteria
				.add(Expression.like("name", addWildcards(filename.getValue())));
	}

	/**
	 * Visits a SearchStartFileDate search criterion.
	 * 
	 * @param date
	 *            The SearchStartFileDate to be visited.
	 * @see uk.me.mukherjee.archivedb.pd.search.SearchVisitor#visitStartFileDate(uk.me.mukherjee.archivedb.pd.search.criteria.SearchStartFileDate)
	 */
	public void visitStartFileDate(SearchStartFileDate date) {
		criteria.add(Expression.ge("lastModified", date.getValue()));
	}

	/**
	 * Visits a SearchEndFileDate search criterion.
	 * 
	 * @param date
	 *            The SearchEndFileDate to be visited.
	 * @see uk.me.mukherjee.archivedb.pd.search.SearchVisitor#visitEndFileDate(uk.me.mukherjee.archivedb.pd.search.criteria.SearchEndFileDate)
	 */
	public void visitEndFileDate(SearchEndFileDate date) {
		criteria.add(Expression.le("lastModified", date.getValue()));
	}

	/**
	 * Visits a SearchKeyword search criterion.
	 * 
	 * @param keyword
	 *            The SearchKeyword to be visited.
	 * @throws SearchException
	 *             Propogates Hibernate exceptions.
	 * @see uk.me.mukherjee.archivedb.pd.search.SearchVisitor#visitKeyword(uk.me.mukherjee.archivedb.pd.search.criteria.SearchKeyword)
	 */
	public void visitKeyword(SearchKeyword keyword) throws SearchException {
		try {
			Criteria volumeCriteria = criteria.createCriteria("volume");
			Criteria keywordCriteria = volumeCriteria
					.createCriteria("keywords");
			keywordCriteria.add(Expression.like("keyword", keyword.getValue()));
		} catch (HibernateException e) {
			throw new SearchException(e);
		}
	}

	@Override
	protected void buildQuery() throws SearchException {
		for (Iterator<SearchCriterion> itt = criterionList.iterator(); itt
				.hasNext();)
			itt.next().accept(this);
	}

	private LinkedList<SearchCriterion> criterionList = new LinkedList<SearchCriterion>();

	/**
	 * Searches the database for all files matching the search criteria
	 * provided.
	 * 
	 * @param searchCriterionList
	 *            The list of ISearchCriterion objects against which to search.
	 * @return SearchResult representing the files matching the search.
	 * @see uk.me.mukherjee.archivedb.pd.search.SearchVisitor#doSearch(java.util.List)
	 */
	public void doInternalSearch() throws SearchException {
		List fileList;
		try {
			fileList = criteria.list();
		} catch (HibernateException e) {
			throw new SearchException(e);
		}
		VolumeSearchResult searchResult = new VolumeSearchResult();
		searchResult.setFiles(fileList);
	}

}
